﻿namespace LogManager.Gui.ViewModels
{
    using LogManager.Gui.Views;
    using LogManager.Utils.ChangeTracking;
    using System;
    using System.Threading;
    using System.Windows;
    using System.Windows.Threading;
    using LogManager.Gui.FrameworkExtensions;

    /// <summary>
    /// Abstract base class for a ViewModel implementation.
    /// </summary>
    /// <typeparam name="TView">The type of the view. Do provide an interface as type and not the concrete type itself.</typeparam>
    public abstract class ViewModelBase<TView> : DependPropertyChangeBase, IViewModel<TView>
        where TView : class, IView
    {
        public TView View { get; private set; }

        IFrameworkElement IViewModel.View { get { return View; } }

        /// <summary>
        /// Initializes a new instance of the <see cref="ViewModelBase&lt;TView&gt;"/> class and attaches itself as <c>DataContext</c> to the view.
        /// </summary>
        /// <param name="view">The view.</param>
        protected ViewModelBase(TView view)
        {
            if (view == null) { throw new ArgumentNullException("view"); }

            this.View = view;
            SetViewDataContext();
        }


        private void SetViewDataContext()
        {
            // Check if the code is running within the WPF application model
            if (SynchronizationContext.Current is DispatcherSynchronizationContext)
            {
                // Set DataContext of the view has to be delayed so that the ViewModel can initialize the internal data (e.g. Commands)
                // before the view starts with DataBinding.
                Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate()
                {
                    this.View.DataContext = this;
                });
            }
            else
            {
                // When the code runs outside of the WPF application model then we set the DataContext immediately.
                this.View.DataContext = this;
            }
        }
    }
}